/************************************************************************
 * File: game.cpp                                                       *
 *                                                                      *
 * Copyright 2006, 2008 Colin Kern (colin.kern@gmail.com)               *
 *                                                                      *
 * This file is part of Profit.  Some previous versions were released   *
 * under the names Megacorp Mania and Acquire.                          *
 *                                                                      *
 * Profit is free software: you can redistribute it and/or modify       *
 * it under the terms of the GNU General Public License as published by *
 * the Free Software Foundation, either version 3 of the License, or    *
 * any later version.                                                   *
 *                                                                      *
 * Profit is distributed in the hope that it will be useful,            *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 * GNU General Public License for more details.                         *
 *                                                                      *
 * You should have received a copy of the GNU General Public License    *
 * along with Profit.  If not, see <http://www.gnu.org/licenses/>.      *
 ************************************************************************/
#include "game.h"
#include "board.h"
#include "company.h"
#include "player.h"
#include "bag.h"
#include "tile.h"
#include "button.h"
#include "label.h"
#include <QPainter>
#include <QGridLayout>
#include <QTextEdit>
#include <QTextDocument>
#include <QMessageBox>

Game::Game(QWidget *parent)
	: QWidget(parent)
{
	m_board = new Board(0, 0);
	m_bag = new Bag(0, 0);
	m_doneButton = new Button("Done");
	m_endButton = new Button("End Game");
	connect(m_doneButton, SIGNAL(hoverChanged(bool)),
		this, SLOT(doneButtonHoverChanged(bool)));
	connect(m_endButton, SIGNAL(hoverChanged(bool)),
		this, SLOT(endButtonHoverChanged(bool)));
	connect(m_doneButton, SIGNAL(clicked()), this, SLOT(doneClicked()));
	connect(m_endButton, SIGNAL(clicked()), this, SLOT(endClicked()));
	m_instruction = new Label(QFont("Helvetica", 12, QFont::Bold), 
		Qt::AlignVCenter | Qt::AlignHCenter);
	QFont font("Helvetica", 12);
	font.setItalic(true);
	m_leftHelp = new Label(font, Qt::AlignVCenter | Qt::AlignLeft);
	m_rightHelp = new Label(font, Qt::AlignVCenter | Qt::AlignRight);
}

void Game::advanceTurnCounter(Player *&turn) const
{
	if (turn == 0 || turn == m_players.last()) {
		turn = m_players.first();
	} else {
		turn = m_players[m_players.indexOf(turn) + 1];
	}
}

void Game::setBoardSize(int rows, int columns)
{
	delete m_board;
	m_board = new Board(rows, columns);
	m_bag->reset(rows, columns);
	connect(m_board, SIGNAL(slotClicked(int, int)), 
		this, SLOT(boardClicked(int, int)));
	for (int row = 0; row < rows; ++row) {
		for (int column = 0; column < columns; ++column) {
			connect(this, SIGNAL(phaseChanged(Profit::Phase)),
				m_board->getSlot(row, column), SLOT(changePhase(Profit::Phase)));
			connect(m_board->getSlot(row, column), SIGNAL(hoverChanged(bool, int, int)),
				this, SLOT(boardHoverChanged(bool, int, int)));
		}
	}
}

void Game::addCompany(Company *company)
{
	m_companies.append(company);
	connect(this, SIGNAL(phaseChanged(Profit::Phase)),
		m_companies.last(), SLOT(changePhase(Profit::Phase)));
	connect(m_companies.last(), SIGNAL(clicked(Company*)),
		this, SLOT(companyClicked(Company*)));
	connect(this, SIGNAL(newTurn(Player*)), 
		m_companies.last(), SLOT(setTurn(Player*)));
	connect(m_companies.last(), SIGNAL(sizeChanged(int)),
		this, SLOT(companySizeChanged(int)));
	connect(m_companies.last(), SIGNAL(hoverChange(bool, Company*)),
		this, SLOT(companyHoverChanged(bool, Company*)));
}

void Game::addPlayer(Player *player)
{
	m_players.append(player);
}

void Game::clearPlayers()
{
	m_players.clear();
}

void Game::setupGUI()
{
	QGridLayout *layout = new QGridLayout;
	QVBoxLayout *companyLayout = new QVBoxLayout;
	QVBoxLayout *playerLayout = new QVBoxLayout;
	QHBoxLayout *topLayout = new QHBoxLayout;
	
	topLayout->addWidget(m_doneButton);
	QVBoxLayout *labels = new QVBoxLayout;
	labels->addWidget(m_instruction);
	labels->setSpacing(2);
	labels->setContentsMargins(11, 2, 11, 2);
	QHBoxLayout *help = new QHBoxLayout;
	help->addWidget(m_leftHelp);
	help->addWidget(m_rightHelp);
	labels->addLayout(help);
	topLayout->addLayout(labels);
	topLayout->addWidget(m_endButton);
	
	layout->addLayout(topLayout, 0, 0, 1, 2);
	
	QListIterator<Company*> i(m_companies);
	while (i.hasNext()) {
		companyLayout->addWidget(i.next());
	}
	layout->addLayout(companyLayout, 1, 0);
	layout->addWidget(m_board, 1, 1);
	
	QListIterator<Player*> player(m_players);
	while (player.hasNext()) {
		playerLayout->addWidget(player.next());
	}
	layout->addLayout(playerLayout, 2, 0, 1, 2);
	
	delete this->layout();
	setLayout(layout);
}

void Game::setStartingCash(int value)
{
	m_startingCash = value;
}

void Game::setInitialShares(int value)
{
	m_initialShares = value;
}

void Game::setTilesInHand(int value)
{
	m_tilesInHand = value;
}

void Game::setSafeSize(int value)
{
	m_safeSize = value;
}

void Game::setBuyLimit(int value)
{
	m_buyLimit = value;
}

void Game::setMonopolySize(int value)
{
	m_monopolySize = value;
}

void Game::reset()
{
	m_endButton->disable();
	m_board->reset();
	m_bag->reset(m_board->nRows(), m_board->nColumns());
	QMutableListIterator<Company*> i(m_companies);
	while (i.hasNext()) {
		i.next()->reset(m_initialShares);
	}
	QMutableListIterator<Player*> j(m_players);
	while (j.hasNext()) {
		Player *player = j.next();
		player->reset(m_companies);
		player->giveMoney(m_startingCash);
		placeTileFromBag();
	}
	
	emit message("<b>Game started</b>");
	m_turn = 0;
	nextTurn();
}

void Game::placeTileFromBag()
{
	if (!m_bag->isEmpty()) {
		m_board->placeTile(m_bag->draw());
	}
}

void Game::nextTurn()
{
	if (m_turn) {
		m_turn->setHighlight(Player::None);
	}
	
	advanceTurnCounter(m_turn);
	
	m_turn->setHighlight(Player::Turn);
	
	bool hasValid = false;
	QListIterator<Tile> i(m_turn->getTileIterator());
	while (i.hasNext()) {
		Tile tile = i.next();
		Validity validity = isValidTile(tile);
		if (validity == Invalid) {
			m_turn->removeTile(tile);
		} else if (validity == Temporary) {
			m_board->getSlot(tile)->setValid(false);
		} else {
			hasValid = true;
			m_board->getSlot(tile)->setValid(true);
		}
	}
	
	while (m_turn->nTiles() < m_tilesInHand && !m_bag->isEmpty()) {
		Tile tile = m_bag->draw();
		Validity validity = isValidTile(tile);
		if (validity != Invalid) {
			m_turn->giveTile(tile);
			if (validity == Temporary) {
				m_board->getSlot(tile)->setValid(false);
			} else {
				hasValid = true;
				m_board->getSlot(tile)->setValid(true);
			}
		}
	}
	
	m_board->clearHighlights();
	i = m_turn->getTileIterator();
	while (i.hasNext()) {
		m_board->highlightTile(i.next(), BoardSlot::InHand);
	}
	
	m_turn->setBuyLimit(m_buyLimit);
	
	emit message("<b>" + m_turn->getName() + "'s turn</b>");
	
	emit newTurn(m_turn);
	if (hasValid) {
		changePhase(Profit::PlaceTile);
	} else {
		changePhase(Profit::BuyShares);
	}
}

Game::Validity Game::isValidTile(const Tile &tile)
{
	QList<Tile> adjacents = m_board->placeTile(tile);
	QList<Company*> companies = m_board->findCompanies(adjacents);
	
	m_board->removeTile(tile);
    
    int safeCompanies = 0;
    
	//Test if tile connects two or more companies
    if (companies.size() > 1) {
        QListIterator<Company*> i(companies);
		while (i.hasNext()) {
			if (i.next()->getSize() >= m_safeSize) {
				safeCompanies++;
			}
		}
        if (safeCompanies > 1) {
            return Invalid;
		}
    }
    
	//Test if tile creates an unowned group, but there are no available companies
	if (adjacents.size() > 1 && companies.empty()) {
		QListIterator<Company*> i(m_companies);
		while (i.hasNext()) {
			if (i.next()->getSize() == 0) {
				return Valid;
			}
		}
		
		return Temporary;
	}
	
    return Valid;
}

void Game::changePhase(Profit::Phase phase)
{
	clearHelp();
	m_phase = phase;
	emit phaseChanged(m_phase);
	
	if (m_phase == Profit::PlaceTile) {
		m_instruction->setText("Choose a tile to place");
		m_doneButton->disable();
	} else if (m_phase == Profit::FormCompany) {
		m_instruction->setText("Choose a company to form");
		m_doneButton->disable();
	} else if (m_phase == Profit::ChooseMerge) {
		m_instruction->setText("Choose which company remains");
		m_doneButton->disable();
		clearCompanyMergeFlags();
		QListIterator<Company*> i(m_phaseCompanies);
		while (i.hasNext()) {
			Company* company = i.next();
			if (company->getSize() == m_phaseCompanies.first()->getSize()) {
				company->setInMerge();
			}
		}
	} else if (m_phase == Profit::MergeCompanies) {
		if (m_mergeTurn->nShares(m_phaseCompanies.at(1)) > 0) {
			m_instruction->setText("Sell, trade, or keep your " +
				m_phaseCompanies.at(1)->getName() + " shares");
			m_doneButton->enable();
		} else {
			nextMergeTurn();
			return;
		}	
	} else if (m_phase == Profit::BuyShares) {
		QListIterator<Company*> i(m_companies);
		bool ok = false;
		while (i.hasNext()) {
			if (i.next()->canBuy(m_turn)) {
				ok = true;
			}
		}
		if (!ok) {
			nextTurn();
			return;
		}
		m_instruction->setText("Buy shares (" + 
			QString::number(m_turn->getBuyLimit()) + " left)");
		m_doneButton->enable();
	}
	
	if ((m_turn->isComputer() && m_phase != Profit::MergeCompanies) ||
		(m_phase == Profit::MergeCompanies && m_mergeTurn->isComputer())) {
		m_doneButton->disable();
		aiPhase();
	}
}

void Game::setupMergePhase()
{
	if (m_phaseCompanies.size() < 2) {
		m_turn->setHighlight(Player::Turn);
		changePhase(Profit::BuyShares);
	} else {
		m_turn->setHighlight(Player::DimTurn);
		payBenefits(m_phaseCompanies.at(1));
		m_mergeTurn = 0;
		nextMergeTurn();
	}
}

void Game::formNewCompany(Company *company)
{
	QListIterator<Tile> i(m_phaseTiles);
	while (i.hasNext()) {
		m_board->getSlot(i.next())->setOwner(company);
		company->increaseSize(1);
	}
	if (company->nShares() > 0) {
		giveShare(m_turn, company);
		updateMajorities(company);
	}
	emit message(company->getName() + " formed");
}

void Game::growCompany()
{
	QListIterator<Tile> i(m_phaseTiles);
	while (i.hasNext()) {
		Tile tile = i.next();
		if (!m_board->getSlot(tile)->isOwned()) {
			m_board->getSlot(tile)->setOwner(m_phaseCompanies.first());
			m_phaseCompanies.first()->increaseSize(1);
		}
	}
	emit message(m_phaseCompanies.first()->getName() + " has grown");
}

void Game::mergeCompanies(Company *big, Company *small)
{
	QListIterator<Tile> i(m_phaseTiles);
	while (i.hasNext()) {
		Tile tile = i.next();
		if (!m_board->getSlot(tile)->isOwned() || 
			m_board->getSlot(tile)->getOwner() == small) {
			m_board->getSlot(tile)->setOwner(big);
			big->increaseSize(1);
		}
	}
	small->setSize(0);
	emit message(small->getName() + " is now part of " + big->getName());
}

void Game::clearCompanyMergeFlags()
{
	QListIterator<Company*> i(m_companies);
	while (i.hasNext()) {
		i.next()->unsetInMerge();
	}
}

void Game::nextMergeTurn()
{
	if (!m_mergeTurn) {
		m_mergeTurn = m_turn;
	} else {
		m_mergeTurn->setHighlight(Player::None);
		advanceTurnCounter(m_mergeTurn);
		if (m_mergeTurn == m_turn) {
			mergeCompanies(m_phaseCompanies.first(), m_phaseCompanies.at(1));
			m_phaseCompanies.removeAt(1);
			setupMergePhase();
			return;
		}
	}
	
	clearCompanyMergeFlags();
	updateCompaniesInMerge();
	m_mergeTurn->setHighlight(Player::Merge);
	changePhase(Profit::MergeCompanies);
}

void Game::updateMajorities(Company *company)
{
	QListIterator<Player*> i(m_players);
	QList<Player*> majority;
	QList<Player*> minority;
	while (i.hasNext()) {
		Player *player = i.next();
		player->setMajority(company, false);
		player->setMinority(company, false);
		if (player->nShares(company) > 0) {
			if (majority.empty()) {
				majority.append(player);
			} else if (majority.first()->nShares(company) == 
					player->nShares(company)) {
				majority.append(player);
			} else if (majority.first()->nShares(company) <
					player->nShares(company)) {
				minority = majority;
				majority.clear();
				majority.append(player);
			} else if (minority.empty()) {
				minority.append(player);
			} else if (minority.first()->nShares(company) ==
					player->nShares(company)) {
				minority.append(player);
			} else if (minority.first()->nShares(company) <
					player->nShares(company)) {
				minority.clear();
				minority.append(player);
			}
		}
	}
	if (minority.empty() || majority.size() > 1) {
		minority = majority;
	}
	
	i = QListIterator<Player*>(majority);
	while (i.hasNext()) {
		i.next()->setMajority(company);
	}
	
	i = QListIterator<Player*>(minority);
	while (i.hasNext()) {
		i.next()->setMinority(company);
	}
}

void Game::payBenefits(Company *company)
{
	int nMajority = 0;
	int nMinority = 0;
	
	QListIterator<Player*> i(m_players);
	while (i.hasNext()) {
		Player *player = i.next();
		if (player->isMajority(company)) {
			nMajority++;
		}
		if (player->isMinority(company)) {
			nMinority++;
		}
	}
	
	i.toFront();
	while (i.hasNext()) {
		Player *player = i.next();
		qreal benefits = 0;
		if (player->isMajority(company)) {
			benefits += company->getMajorityBenefits() / (qreal)nMajority;
		}
		if (player->isMinority(company)) {
			benefits += company->getMinorityBenefits() / (qreal)nMinority;
		}
		
		if (benefits - (int)benefits >= .5) {
			benefits += 1;
		}
		if ((int)benefits > 0) {
			player->giveMoney((int)benefits);
			emit message(player->getName() + " receives $" +
				QString::number((int)benefits) + " in benefits");
		}
	}
}

void Game::buyShare(Player *player, Company *company)
{
	company->takeShares(1);
	player->giveShares(company, 1);
	player->takeMoney(company->getPricePerShare());
	m_turn->setBuyLimit(m_turn->getBuyLimit() - 1);
	updateMajorities(company);
	updateCompanies();
}

void Game::sellShare(Player *player, Company *company)
{
	player->giveMoney(company->getPricePerShare());
	player->takeShares(company, 1);
	company->giveShares(1);
	updateMajorities(company);
}

void Game::tradeShare(Player *player, Company *big, Company *small)
{
	big->takeShares(1);
	player->giveShares(big, 1);
	small->giveShares(2);
	player->takeShares(small, 2);
}

void Game::giveShare(Player *player, Company *company)
{
	company->takeShares(1);
	player->giveShares(company, 1);
}

void Game::updateCompanies()
{
	QListIterator<Company*> i(m_companies);
	while (i.hasNext()) {
		i.next()->updateCurrentColor();
	}
}

void Game::clearHelp()
{
	m_leftHelp->setText("");
	m_rightHelp->setText("");
}

void Game::setHelp(const QString &left, const QString &right)
{
	m_leftHelp->setText(left);
	m_rightHelp->setText(right);
}

void Game::updateCompaniesInMerge()
{
	if (m_mergeTurn->canTrade(m_phaseCompanies.first(), 
			m_phaseCompanies.at(1))) {
		m_phaseCompanies.first()->setInMerge();
	} else {
		m_phaseCompanies.first()->unsetInMerge();
	}
	if (m_mergeTurn->canSell(m_phaseCompanies.at(1))) {
		m_phaseCompanies.at(1)->setInMerge();
	} else {
		m_phaseCompanies.at(1)->unsetInMerge();
	}
}

void Game::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);
	
	QLinearGradient gradient(rect().topLeft(), rect().bottomRight());
	gradient.setColorAt(0.0, Qt::black);
	gradient.setColorAt(1.0, QColor(64, 64, 64));
	
	painter.setPen(Qt::NoPen);
	painter.setBrush(QBrush(gradient));
	painter.drawRect(rect());
}

void Game::boardClicked(int row, int column)
{
	if (m_phase == Profit::PlaceTile) {
		if (m_turn->hasTile(Tile(row, column)) && 
				isValidTile(Tile(row, column)) == Valid) {
			emit message(m_turn->getName() + " played " + 
				Tile::toString(row, column));
			m_phaseTiles = m_board->placeTile(Tile(row, column));
			m_turn->removeTile(Tile(row, column));
			m_phaseCompanies = m_board->findCompanies(m_phaseTiles);
			if (m_phaseTiles.size() > 1 && m_phaseCompanies.empty()) {
				changePhase(Profit::FormCompany);
			} else if (m_phaseCompanies.size() == 1) {
				growCompany();
				changePhase(Profit::BuyShares);
			} else if (m_phaseCompanies.size() > 1) {
				QList<Company*> sorted;
				while (!m_phaseCompanies.empty()) {
					QListIterator<Company*> i(m_phaseCompanies);
					Company *largest = i.next();
					while (i.hasNext()) {
						Company *c = i.next();
						if (c->getSize() > largest->getSize()) {
							largest = c;
						}
					}
					sorted.append(largest);
					m_phaseCompanies.removeAll(largest);
				}
				m_phaseCompanies = sorted;
				m_mergeTurn = m_turn;
				
				if (m_phaseCompanies.first()->getSize() > 
						m_phaseCompanies.at(1)->getSize()) {
					setupMergePhase();
				} else {
					changePhase(Profit::ChooseMerge);
				}
			} else {
				changePhase(Profit::BuyShares);
			}
		} else if (m_turn->isComputer()) {
			QMessageBox::warning(this, "Uh oh", "The AI tried to play a "
				"tile it didn't have or wasn't valid (" + 
				Tile::toString(row, column));
		}
	}
}

void Game::companyClicked(Company *company)
{
	if (m_phase == Profit::FormCompany) {
		if (company->getSize() == 0) {
			formNewCompany(company);
			changePhase(Profit::BuyShares);
		} else if (m_turn->isComputer()) {
			QMessageBox::warning(this, "Uh oh", "The AI tried to form a "
				"company that already existed");
		}
	} else if (m_phase == Profit::BuyShares) {
		if (company->canBuy(m_turn)) {
			buyShare(m_turn, company);
			m_instruction->setText("Buy shares (" + 
				QString::number(m_turn->getBuyLimit()) + " left)");
		}
	} else if (m_phase == Profit::MergeCompanies) {
		if (company == m_phaseCompanies.first() && company->inMerge()) {
			tradeShare(m_mergeTurn, company, m_phaseCompanies.at(1));
			updateCompaniesInMerge();
		} else if (company == m_phaseCompanies.at(1) && company->inMerge()) {
			sellShare(m_mergeTurn, company);
			updateCompaniesInMerge();
		}
	} else if (m_phase == Profit::ChooseMerge) {
		if (company->inMerge()) {
			emit message(m_turn->getName() + " chooses " + company->getName());
			if (company != m_phaseCompanies.first()) {
				m_phaseCompanies.swap(0, m_phaseCompanies.indexOf(company));
			}
			payBenefits(m_phaseCompanies.at(1));
			changePhase(Profit::MergeCompanies);
		} else if (m_turn->isComputer()) {
			QMessageBox::warning(this, "Uh oh", "The AI chose a company "
				"that wasn't involved in the merge.");
		}
	}
}

void Game::doneClicked()
{
	if (m_phase == Profit::BuyShares) {
		nextTurn();
	} else if (m_phase == Profit::MergeCompanies) {
		nextMergeTurn();
	}
}

void Game::endClicked()
{
	QListIterator<Company*> i(m_companies);
	while (i.hasNext()) {
		Company *company = i.next();
		payBenefits(company);
		QListIterator<Player*> j(m_players);
		while (j.hasNext()) {
			Player *player = j.next();
			while (player->nShares(company) > 0) {
				sellShare(player, company);
			}
		}
	}
	emit message(m_turn->getName() + " has ended the game");
	emit gameEnded();
}

void Game::companySizeChanged(int size)
{
	if (size >= m_monopolySize) {
		m_endButton->enable();
	} else if (size > m_safeSize) {
		QListIterator<Company*> i(m_companies);
		bool ok = true;
		bool exists = false;
		while (i.hasNext()) {
			Company *company = i.next();
			if (company->getSize() > 0) {
				exists = true;
				if (company->getSize() < m_safeSize) {
					ok = false;
				}
			}
		}
		if (ok && exists) {
			m_endButton->enable();
		}
	}
}

void Game::companyHoverChanged(bool hover, Company *company)
{
	if (!hover) {
		clearHelp();
	} else {
		if (m_phase == Profit::BuyShares && company->canBuy(m_turn)) {
			setHelp("Buy 1 share");
		} else if (m_phase == Profit::MergeCompanies) {
			if (m_phaseCompanies.first() == company &&
					company->inMerge()) {
				setHelp("Trade 2 " + m_phaseCompanies.at(1)->getName() +
					" for 1 " + company->getName());
			} else if (m_phaseCompanies.at(1) == company &&
					company->inMerge()) {
				setHelp("Sell 1 " + company->getName());
			}
		} else if (m_phase == Profit::FormCompany) {
			if (company->getSize() == 0) {
				setHelp("Form " + company->getName());
			}
		} else if (m_phase == Profit::ChooseMerge) {
			if (m_phaseCompanies.contains(company)) {
				setHelp("Choose " + company->getName() 
					+ " to acquire the others");
			}
		}
	}
}

void Game::boardHoverChanged(bool hover, int row, int column)
{
	if (!hover) {
		clearHelp();
	} else if (m_phase == Profit::PlaceTile) {
		if (m_turn->hasTile(Tile(row, column))) {
			Validity validity = isValidTile(Tile(row, column));
			if (validity == Valid) {
				setHelp("Place tile");
			} else if (validity == Temporary) {
				setHelp("Can't place: No companies available");
			}
		}
	}
}

void Game::doneButtonHoverChanged(bool hover)
{
	if (!hover || !m_doneButton->enabled()) {
		clearHelp();
	} else if (m_phase == Profit::BuyShares) {
		setHelp("End turn");
	} else if (m_phase == Profit::MergeCompanies) {
		setHelp("Done trading and selling");
	}
}

void Game::endButtonHoverChanged(bool hover)
{
	if (!hover) {
		clearHelp();
	} else if (m_endButton->enabled()) {
		setHelp("End the game");
	} else {
		setHelp("End game conditions not met");
	}
}

void Game::aiPhase()
{
	if (m_phase == Profit::PlaceTile) {
		Tile tile = aiChooseTile(m_turn);
		boardClicked(tile.getRow(), tile.getColumn());
	} else if (m_phase == Profit::FormCompany) {
		companyClicked(aiChooseNewCompany(m_turn));
	} else if (m_phase == Profit::ChooseMerge) {
		companyClicked(aiChooseMerge(m_turn));
	} else if (m_phase == Profit::MergeCompanies) {
		aiMergeCompany(m_mergeTurn, m_phaseCompanies.first(),
			m_phaseCompanies.at(1));
		doneClicked();
	} else if (m_phase == Profit::BuyShares) {
		aiBuyStock(m_turn);
		doneClicked();
	}
}

void Game::aiSetDesirability(Player *ai)
{
	ai->resetAiDesire();
    
    //SET DESIRABILITY FOR COMPANY SHARES
	QListIterator<Company*> i(m_companies);
	while (i.hasNext()) {
		Company *company = i.next();    
		
		//More desirable if cheaper/smaller
		////Adds from 0-10
		ai->adjustAiDesire(company,	(1200 - company->getPricePerShare()) / 100);

		//More desirable if there is no minority
		////Adds 25
		bool isMinority = false;
		QListIterator<Player*> players(m_players);
		while (players.hasNext()) {
			if (players.next()->isMinority(company)) {
				isMinority = true;
			}
		}
		if (!isMinority == false) {
			ai->adjustAiDesire(company, 25);
		}

		//More desirable if ai is majority and minority is 3 or less behind
		////Adds 35
		if (ai->isMajority(company)) {
			Player *minority = 0;
			//Find minority
			players.toFront();
			while (players.hasNext()) {
				if (players.next()->isMinority(company)) {
					minority = players.peekPrevious();
				}
			}
			if (minority && 
					ai->nShares(company) + 3 >= minority->nShares(company)) {
				ai->adjustAiDesire(company, 35);
			}
		}

		//More desirable if ai is minority and majority is 3 or less behind
		////Adds 40
		if (ai->isMinority(company)) {
			Player *majority = 0;
			//Find majority
			players.toFront();
			while (players.hasNext()) {
				if (players.next()->isMajority(company)) {
					majority = players.peekPrevious();
				}
				if (majority &&
						ai->nShares(company) + 3 >= majority->nShares(company)) {
					ai->adjustAiDesire(company, 40);
				}
			}
		}
		
		//More desirable if ai is minority at all
		////Adds 10
		if (ai->isMinority(company)) {
			ai->adjustAiDesire(company, 10);
		}

		//More desirable if ai is majority at all
		////Adds 15
		if (ai->isMajority(company)) {
			ai->adjustAiDesire(company, 15);
		}

		//Less desirable if ai already has some
		////Subtracts 2 for every share owned
		ai->adjustAiDesire(company, -ai->nShares(company) * 2);

		//Less desirable if other players already own stock
		////Subtracts 5 for each player who owns some
		players.toFront();
		while (players.hasNext()) {
			if (players.next()->nShares(company) > 0 ) {
				ai->adjustAiDesire(company, -5);
			}
		}
		
		//Don't buy if ai is majority and minority is more than 3 behind
		if (ai->isMajority(company)) {
			players.toFront();
			while (players.hasNext()) {
				Player *player = players.next();
				if (player->isMinority(company) && 
						player->nShares(company) < ai->nShares(company) - 3) {
					ai->setAiDesire(company, 0);
				}
				//Don't buy if ai is majority and there is not enough stock left
				////for someone to take the majority
				else if (player->isMinority(company) && company->nShares() < 
						ai->nShares(company) - player->nShares(company)) {
					ai->setAiDesire(company, 0);
				}
				//Don't buy if ai is majority and no one can afford to take the
				////majority from him
				else if (player->isMinority(company) && player->getMoney() <
							(ai->nShares(company) - player->nShares(company)) *
							company->getPricePerShare()) {
					ai->setAiDesire(company, 0);
				}
			}
		}

		if (ai->isMinority(company)) {
			players.toFront();
			while (players.hasNext()) {
				Player *player = players.next();
				//Don't buy if there isn't enough stock left to get majority
				if (player->isMajority(company) && company->nShares() <
						player->nShares(company) - ai->nShares(company)) {
					ai->setAiDesire(company, 0);
				}
				//Don't buy if there isn't enough money to get majority
				else if (player->isMajority(company) && ai->getMoney() <
						(player->nShares(company) - ai->nShares(company)) *
						company->getPricePerShare()) {
					ai->setAiDesire(company, 0);
				}
			}
		}

		//Don't buy if there is no stock left
		if (company->nShares() == 0) {
			ai->setAiDesire(company, 0);
		}

		//Don't buy if it doesn't exist
		if (company->getSize() == 0) {
			ai->setAiDesire(company, 0);
		}
	}
}

Company *Game::aiChooseNewCompany(Player *ai)
{
    Company *choice = 0;
    
    //See if ai is a majority in dead company
	QListIterator<Company*> i(m_companies);
	while (i.hasNext()) {
		Company *company = i.next();
		if (company->getSize() == 0 && ai->isMajority(company)) {
			if (!choice) {
				choice = company;
			} else if (ai->nShares(choice) < ai->nShares(company)) {
				//Choose majority company with most stock
				choice = company;
			}
		}
	}
    
    //Return if found a majority
    if (choice) {
        return choice;
	}

    //See if ai is a minority in dead company
	i.toFront();
	while (i.hasNext()) {
		Company *company = i.next();
		if (company->getSize() == 0 && ai->isMinority(company)) {
			if (!choice) {
				choice = company;
			} else if (ai->nShares(choice) < ai->nShares(company)) {
			    //Choose minority company with most stock
				choice = company;
			}
		}
	}
    
    //Return if found a minority
    if (choice) {
        return choice;
	}

    //See if ai has shares of any dead company
	i.toFront();
	while (i.hasNext()) {
		Company *company = i.next();
		if (company->getSize() == 0 && ai->nShares(company) > 0) {
			if (!choice) {
				choice = company;
			} else if (ai->nShares(choice) < ai->nShares(company)) {
				choice = company;
			}
		}
	}
    
    //Return if found stock in a dead company
    if (choice) {
        return choice;
	}

    //Choose a random company
    do {
		int n = qrand() % m_companies.size();
		i.toFront();
		while (n-- > 0) i.next();
        choice = i.next();
    } while (choice->getSize() > 0);
    
    return choice;
}

Company *Game::aiChooseMerge(Player *ai)
{
	QListIterator<Company*> i(m_phaseCompanies);
	while (i.hasNext()) {
		Company *company = i.next();
		if (company->getSize() == m_phaseCompanies.first()->getSize()) {
			if (ai->isMajority(company)) {
				return company;
			}
		}
	}
	
	i.toFront();
	while (i.hasNext()) {
		Company *company = i.next();
		if (company->getSize() == m_phaseCompanies.first()->getSize()) {
			if (ai->isMinority(company)) {
				return company;
			}
		}
	}
	
	return m_phaseCompanies.first();
}

void Game::aiMergeCompany(Player *ai, Company *big, Company *small)
{
    //If ai has no stocks, end
    if (ai->nShares(small) == 0) {
        return;
	}
    
    //Keep stocks, if reasonable
    int total = 0;  //Find total size of companies
	QListIterator<Company*> i(m_companies);
	while (i.hasNext()) {
		total += i.next()->getSize();
	}
    
    if (total < (m_board->nRows() * m_board->nColumns()) / 4) {
        return;
	}

    //Convert stocks, if wanted
    int traded = 0;
    aiSetDesirability(ai);
    while (ai->getAiDesire(big) > 0 && big->nShares() > 0 
        && ai->nShares(small) > 1) {
		tradeShare(ai, big, small);
        traded += 2;
        aiSetDesirability(ai);
    }

    if (traded > 0) {
		emit message(ai->getName() + " traded " + QString::number(traded) +
			" shares of " + small->getName() + " for " +
			QString::number(traded / 2) + " shares of " + big->getName());
	}
	
    //Sell remaining stocks
    int sold = 0;
    while (ai->nShares(small) > 0) {
		sellShare(ai, small);
        sold++;
    }

    if (sold > 0) {
		emit message(ai->getName() + " sold " + QString::number(sold) +
			" shares of " + small->getName() + " at $" +
			QString::number(small->getPricePerShare()) + " per share");
	}
	
	if (sold == 0 && traded == 0) {
		emit message(ai->getName() + " decided to keep his/her shares of " +
			small->getName());
	}
}

void Game::aiBuyStock(Player *ai)
{
	if (m_endButton->enabled()) {
		endClicked();
		return;
	}
	
    bool done = false;
    Company *c1 = 0;
    Company *c2 = 0;
    Company *c3 = 0;
    int a1 = 0;
    int a2 = 0;
    int a3 = 0;
    Company *max = 0;

	aiSetDesirability(ai);
    do {
		if (ai->getBuyLimit() == 0) {
			done = true;
			break;
		}
		
        max = 0;
		QListIterator<Company*> i(m_companies);
		while (i.hasNext()) {
			Company *company = i.next();
			if (!max) {
				max = company;
			} else if (ai->getAiDesire(company) > ai->getAiDesire(max) &&
                company->getSize() > 0) {
                max = company;
			}
		}

		if (ai->getAiDesire(max) <= 0) {
			done = true;
		} else if (max->nShares() > 0 && 
				ai->getMoney() >= max->getPricePerShare()) {
			// Buy one
            buyShare(ai, max);
            
            if (!c1) {
                c1 = max;
                a1++;
            }
            else if (c1 == max) {
                a1++;
            }
            else if (!c2) {
                c2 = max;
                a2++;
            }
            else if (c2 == max) {
                a2++;
            }
            else if (!c3) {
                c3 = max;
                a3++;
            }
            else if (c3 == max) {
                a3++;
            }
			aiSetDesirability(ai);
        }
        else {
			ai->setAiDesire(max, 0);
        }
		
    } while (!done);

    //Do message if ai bought anything
    if (c1) {
		emit message(ai->getName() + " bought " + QString::number(a1) +
			" shares of " + c1->getName() + " at $" + 
			QString::number(c1->getPricePerShare()) + " per share");
    }
    if (c2) {
		emit message(ai->getName() + " bought " + QString::number(a2) +
			" shares of " + c2->getName() + " at $" + 
			QString::number(c2->getPricePerShare()) + " per share");
    }
    if (c3) {
		emit message(ai->getName() + " bought " + QString::number(a3) +
			" shares of " + c3->getName() + " at $" + 
			QString::number(c3->getPricePerShare()) + " per share");
    }
}

Tile Game::aiChooseTile(Player *ai)
{
	int best = -1;
	Tile rval;
	QListIterator<Tile> i(ai->getTileIterator());
	while (i.hasNext()) {
		Tile tile = i.next();
		if (isValidTile(tile) == Valid) {
			int value = 0;
			QList<Tile> tiles = m_board->placeTile(tile, true);
			QList<Company*> companies = m_board->findCompanies(tiles);
			m_board->removeTile(tile, true);
			if (tiles.size() > 1) {
				if (companies.size() == 0) {
					QListIterator<Company*> j(m_companies);
					while (j.hasNext()) {
						if (j.next()->getSize() == 0) {
							value = 10;
						}
					}
				}
	            else if (companies.size() == 1) {
					QListIterator<Company*> j(m_companies);
					while (j.hasNext()) {
						Company *company = j.next();
	                    if (companies.first() == company) {
	                        if (ai->isMajority(company)) {
	                            value = 5;
							}
	                    }
	                }
	            }
	            else if (companies.size() >= 2) {
	                value = 15;
	            }
	        }
			if (best == -1 || value > best) {
				best = value;
				rval = tile;
			}
		}
    }
    
	if (best == -1) {
		QMessageBox::warning(this, "Uh oh", "The AI doesn't have any valid"
			" tiles.");
	}
	
    return rval;
}
